package com.sailfish.springbootdemo.utils;

import com.alibaba.fastjson.JSONObject;
import com.sailfish.springbootdemo.configs.UserHeaderHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.List;

/**
 * sfs接口
 *
 * @author z22968
 * @date 2022/5/20 10:49
 */
@Slf4j
@Component
@PropertySource("classpath:application.yml")
public class SfsUtils {

    @Value("${personal.config.sfs.appId}")
    public String appId;

    @Value("${personal.config.sfs.pwd}")
    public String pwd;

    @Value("${personal.config.sfs.parentFileSid}")
    public String parentFileSid;

    @Value("${personal.config.sfs.baseUrl}")
    public String baseUrl;

//    @Value("${personal.config.sfs.adminDomainAccount}")
//    public String adminAccount;


    //SPEC_APP/CROSS_APP(本应用专属/跨应用访问)
    public String shareLevel = "SPEC_APP";

    // token
    private static String eosToken;

    // 过期时间
    private static long tokenExpireTime;

    RestTemplate restTemplate = new RestTemplate();

    /**
     * 获取sfs token
     *
     * @return java.lang.String
     * @author z22968
     * @date 2022/5/20 10:49
     */
    public String getToken() {
        if (StringUtils.isEmpty(eosToken) || tokenExpireTime < System.currentTimeMillis()) {
            try {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("appId", appId);
                jsonObject.put("pwd", pwd);
                String result = HttpUtil.sendPostJson(baseUrl + "/user/login", jsonObject);
                SfsResponse response = JSONObject.parseObject(result, SfsResponse.class);
                eosToken = response.getToken();
            } catch (Exception e) {
                String message = e.getMessage();
            }
//            Map<String, String> accountMap = new HashMap<>();
//            accountMap.put("appId", appId);
//            accountMap.put("pwd", pwd);

//            ResponseEntity<SfsResponse> tokenResp = restTemplate.postForEntity(baseUrl + "/user/login", accountMap, SfsResponse.class);
//            SfsResponse response = tokenResp.getBody();
//            if (!(response != null && response.getFlag() && response.getCode() == 200)) {
//                throw new RuntimeException("获取sfs token接口异常，异常信息：" + response.getMessage());
//            }
//            eosToken = response.getToken();
//            // 20分钟过期
            tokenExpireTime = System.currentTimeMillis() + 20 * 60 * 1000;
        }
        return eosToken;
    }

    /**
     * 上传文件
     *
     * @param file
     * @return com.h3c.ecsup.utils.SfsUtils.SfsResponse<com.h3c.ecsup.utils.SfsUtils.SfsFileData>
     * @author z22968
     * @date 2022-05-20 12:06
     */
    public SfsFileData upload(MultipartFile file, String secretKey) throws Exception {
        String adminAccount = UserHeaderHolder.getDomainAccount();
        System.out.println(adminAccount);
        log.info(adminAccount);
        ByteArrayResource resource = new ByteArrayResource(file.getBytes()) {
            @Override
            public String getFilename() {
                return file.getOriginalFilename();
            }
        };
        StringBuilder requestBodyBuilder = new StringBuilder();

        // 添加文件部分
        requestBodyBuilder.append("--").append("boundary").append("\r\n");
        requestBodyBuilder.append("Content-Disposition: form-data; name=\"files\"; filename=\"").append(file.getOriginalFilename()).append("\"\r\n");
        requestBodyBuilder.append("Content-Type: ").append(file.getContentType()).append("\r\n\r\n");
        // 注意：这里不实际添加文件内容，因为它是二进制数据，只展示结构
        requestBodyBuilder.append("[BINARY DATA]").append("\r\n");

        // 添加shareLevel部分
        requestBodyBuilder.append("--").append("boundary").append("\r\n");
        requestBodyBuilder.append("Content-Disposition: form-data; name=\"shareLevel\"\r\n\r\n");
        requestBodyBuilder.append(shareLevel).append("\r\n");

        // 添加path部分
        requestBodyBuilder.append("--").append("boundary").append("\r\n");
        requestBodyBuilder.append("Content-Disposition: form-data; name=\"path\"\r\n\r\n");
        requestBodyBuilder.append(parentFileSid).append("\r\n");

        // 添加secretKey部分
        requestBodyBuilder.append("--").append("boundary").append("\r\n");
        requestBodyBuilder.append("Content-Disposition: form-data; name=\"secretKey\"\r\n\r\n");
        requestBodyBuilder.append(secretKey).append("\r\n");

        // 请求体结束标志
        requestBodyBuilder.append("--").append("boundary").append("--\r\n");

        // 日志输出
        log.info("Request Body (Multipart Form Data Structure):\n{}", requestBodyBuilder);

        // 组合body和header，现有代码保持不变
        MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
        body.add("files", resource);
        body.add("shareLevel", shareLevel);
        log.info("shareLevel:" + shareLevel);
        body.add("path", parentFileSid);
        log.info("path:" + parentFileSid);
        if (!StringUtils.hasText(secretKey)) {
            throw new RuntimeException("密钥不能为空");
        }
        body.add("secretKey", secretKey);
        // header
        final String s = body.toString();
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
        httpHeaders.set("Source-Account", appId + ":" + adminAccount);
        log.info("header Source:" + appId + ":" + adminAccount);
        httpHeaders.set("X-Token", getToken());
        log.info("header x-token:" + getToken());
        // 组合body和header
        HttpEntity<Object> entity = new HttpEntity<>(body, httpHeaders);
        // 使用ParameterizedTypeReference进行包装SfsResponse<SfsFileData>
        ParameterizedTypeReference<SfsResponse<SfsFileData>> reference = new ParameterizedTypeReference<SfsResponse<SfsFileData>>() {
        };
        // 发送请求
        ResponseEntity<SfsResponse<SfsFileData>> sfsFileResponse = restTemplate.exchange(baseUrl + "/file", HttpMethod.PUT, entity, reference);
        log.info("baseUrl :" + baseUrl + "/file");
        SfsResponse<SfsFileData> response = sfsFileResponse.getBody();
        if (!(response != null && response.getFlag() && response.getCode() == 200)) {
            throw new RuntimeException("上传文件至sfs发生异常，异常信息：" + response.getMessage());
        }else{
            log.error("上传文件至sfs发生异常，异常信息：" + response.getMessage());
        }
        return response.getData().get(0);
    }


    public SfsFileData upload2(File file, String secretKey) throws Exception {
        String adminAccount = UserHeaderHolder.getDomainAccount();
        log.info("Admin account: {}", adminAccount);

        // 读取文件内容到字节数组
        byte[] fileBytes = Files.readAllBytes(file.toPath());
        ByteArrayResource resource = new ByteArrayResource(fileBytes) {
            @Override
            public String getFilename() {
                return file.getName(); // 获取文件名
            }
        };

        // 获取文件MIME类型
        String contentType = Files.probeContentType(file.toPath());
        if (contentType == null) {
            contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE; // 默认类型
        }

        // 构建日志信息（可选）
        StringBuilder requestBodyBuilder = new StringBuilder();
        // ... [日志构建逻辑保持不变，将file.getOriginalFilename()替换为file.getName()] ...

        MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
        body.add("files", resource);
        body.add("shareLevel", shareLevel);
        log.info("shareLevel: {}", shareLevel);
        body.add("path", parentFileSid);
        log.info("path: {}", parentFileSid);

        if (!StringUtils.hasText(secretKey)) {
            throw new RuntimeException("密钥不能为空");
        }
        body.add("secretKey", secretKey);

        // 设置请求头
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
        httpHeaders.set("Source-Account", appId + ":" + adminAccount);
        log.info("header Source: {}", appId + ":" + adminAccount);
        httpHeaders.set("X-Token", getToken());
        log.info("header x-token: {}", getToken());

        HttpEntity<Object> entity = new HttpEntity<>(body, httpHeaders);
        ParameterizedTypeReference<SfsResponse<SfsFileData>> reference =
                new ParameterizedTypeReference<SfsResponse<SfsFileData>>() {};

        // 发送请求
        ResponseEntity<SfsResponse<SfsFileData>> sfsFileResponse =
                restTemplate.exchange(baseUrl + "/file", HttpMethod.PUT, entity, reference);

        log.info("Request URL: {}", baseUrl + "/file");
        SfsResponse<SfsFileData> response = sfsFileResponse.getBody();

        if (response == null || !response.getFlag() || response.getCode() != 200) {
            String errorMsg = "上传文件至SFS发生异常" +
                    (response != null ? ": " + response.getMessage() : "");
            log.error(errorMsg);
            throw new RuntimeException(errorMsg);
        }
        return response.getData().get(0);
    }


    /**
     * 获取文件预览地址
     *
     * @param fileId
     * @return com.h3c.ecsup.utils.SfsUtils.SfsFileData
     * @author z22968
     * @date 2022-05-20 14:01
     */
    public SfsFileData preview(String fileId, String secretKey) throws Exception {
        String adminAccount = UserHeaderHolder.getDomainAccount();
        // body
        HashMap<String, Object> body = new HashMap<>();
        body.put("fileId", fileId);
//        body.put("enableWatermark", 1);
//        body.put("watermarkContent", CommonUtil.getUserDetail().getUserId());
        if (!StringUtils.hasText(secretKey)) {
            throw new RuntimeException("密钥不能为空");
        }
        body.put("secretKey", secretKey);
        // header
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("Source-Account", appId + ":" + adminAccount);
        httpHeaders.set("X-Token", getToken());
        // 组合body和header
        HttpEntity<Object> entity = new HttpEntity<>(body, httpHeaders);
        // 使用ParameterizedTypeReference进行包装SfsResponse<SfsFileData>
        ParameterizedTypeReference<SfsPreviewResponse<SfsFileData>> reference = new ParameterizedTypeReference<SfsPreviewResponse<SfsFileData>>() {
        };
        // 发送请求
        ResponseEntity<SfsPreviewResponse<SfsFileData>> sfsFileResponse = restTemplate.exchange(baseUrl + "/file/preview/" + fileId, HttpMethod.POST, entity, reference);
        SfsPreviewResponse<SfsFileData> response = sfsFileResponse.getBody();
        if (!(response != null && response.getFlag() && response.getCode() == 200)) {
            throw new Exception("sfs文件预览发生异常，异常信息：" + response.getMessage());
        }
        return response.getData();
    }

    /**
     * sfs 下载附件
     *
     * @param id
     * @param secretKey
     * @return java.io.InputStream
     * @author z22968
     * @date 2022-05-20 17:11
     */
    public InputStream download(String id, String secretKey) throws Exception {
        String adminAccount = UserHeaderHolder.getDomainAccount();
        // header
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("Source-Account", appId + ":" + adminAccount);
        httpHeaders.set("X-Token", getToken());
        if (!StringUtils.hasText(secretKey)) {
            throw new RuntimeException("密钥不能为空");
        }
        // 组合body和header
        HttpEntity<Object> entity = new HttpEntity<>(null, httpHeaders);
        // 发送请求
        ResponseEntity<Resource> response = restTemplate.exchange(baseUrl + "/file/" + id + "?secretKey=" + secretKey, HttpMethod.GET, entity, Resource.class);
        InputStream inputStream = response.getBody().getInputStream();
        return inputStream;
    }

    /**
     * sfs 删除附件
     *
     * @param fileId
     * @return void
     * @author z22968
     * @date 2022-05-20 17:11
     */
//    public void delete(String fileId) throws Exception {
//        // header
//        HttpHeaders httpHeaders = new HttpHeaders();
//        httpHeaders.set("Source-Account", appId + ":" + adminAccount);
//        httpHeaders.set("X-Token", getToken());
//        // 组合body和header
//        HttpEntity<Object> entity = new HttpEntity<>(null, httpHeaders);
//        // 发送请求
//        ResponseEntity<SfsResponse> sfsResponse = restTemplate.exchange(baseUrl + "/file/" + fileId, HttpMethod.DELETE, entity, SfsResponse.class);
//        SfsResponse response = sfsResponse.getBody();
//        if (!(response != null && response.getFlag() && response.getCode() == 200 && response.getMessage().contains("删除已完成"))) {
//            if (response.getMessage().contains("找不到目标资源")) {
//                caseFileMapper.deleteById(fileId);
//            } else {
//                throw new AppBusinessException("调用删除文件接口发生异常，异常信息：" + response.getMessage());
//            }
//        }
//    }

    /**
     * 获取token返回值
     *
     * @author z22968
     * @date 2022-05-20 11:02
     */

    public static class SfsResponse<T> {
        private Boolean flag;
        private Integer code;
        private String message;
        private String traceId;
        private String token;
        private List<T> data;

        public Boolean getFlag() {
            return flag;
        }

        public void setFlag(Boolean flag) {
            this.flag = flag;
        }

        public Integer getCode() {
            return code;
        }

        public void setCode(Integer code) {
            this.code = code;
        }

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }

        public String getTraceId() {
            return traceId;
        }

        public void setTraceId(String traceId) {
            this.traceId = traceId;
        }

        public String getToken() {
            return token;
        }

        public void setToken(String token) {
            this.token = token;
        }

        public List<T> getData() {
            return data;
        }

        public void setData(List<T> data) {
            this.data = data;
        }
    }

    /**
     * 获取token返回值
     *
     * @author z22968
     * @date 2022-05-20 11:02
     */
    public static class SfsPreviewResponse<T> {
        private Boolean flag;
        private Integer code;
        private String message;
        private String traceId;
        private String token;
        private T data;

        public Boolean getFlag() {
            return flag;
        }

        public void setFlag(Boolean flag) {
            this.flag = flag;
        }

        public Integer getCode() {
            return code;
        }

        public void setCode(Integer code) {
            this.code = code;
        }

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }

        public String getTraceId() {
            return traceId;
        }

        public void setTraceId(String traceId) {
            this.traceId = traceId;
        }

        public String getToken() {
            return token;
        }

        public void setToken(String token) {
            this.token = token;
        }

        public T getData() {
            return data;
        }

        public void setData(T data) {
            this.data = data;
        }

    }

    public static class SfsFileData {
        private String fileSid;
        private String name;
        private String state;
        private String previewUrl;

        public String getFileSid() {
            return fileSid;
        }

        public void setFileSid(String fileSid) {
            this.fileSid = fileSid;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getState() {
            return state;
        }

        public void setState(String state) {
            this.state = state;
        }

        public String getPreviewUrl() {
            return previewUrl;
        }

        public void setPreviewUrl(String previewUrl) {
            this.previewUrl = previewUrl;
        }


    }
}
